// 假设我们有一个邻接列表表示的图
//在这三个函数中，graph 是一个邻接列表，其中键是节点ID，值是该节点的所有相邻节点数组。visited 集合用于记录已访问过的节点，以避免重复访问。DFS递归版本直接调用自身探索相邻节点，而迭代版本则使用栈来模拟递归过程；BFS则利用队列实现节点按层级顺序依次访问。
const graph = {
    0: [1, 2],
    1: [0, 3],
    2: [0, 4],
    3: [1],
    4: [2]
  };
  
  //深度优先遍历 (DFS) - 递归版本
  function dfs(nodeId, visited = new Set(), adjList = graph) {
    if (visited.has(nodeId)) return;
    visited.add(nodeId);
    console.log(nodeId); // 输出访问到的节点
  
    for (const neighbor of adjList[nodeId]) {
      dfs(neighbor, visited, adjList);
    }
  }
  
  // 从节点0开始深度优先遍历
  dfs(0);

  //深度优先遍历 (DFS) - 迭代版本（使用栈）
  function dfsIterative(nodeId, adjList = graph) {
    const stack = [nodeId];
    const visited = new Set();
  
    while (stack.length > 0) {
      const nodeId = stack.pop(); // 弹出栈顶元素（后进先出）
      if (!visited.has(nodeId)) {
        visited.add(nodeId);
        console.log(nodeId);
  
        for (const neighbor of adjList[nodeId]) {
          stack.push(neighbor); // 把邻居节点压入栈中
        }
      }
    }
  }
  
  // 从节点0开始深度优先遍历
  dfsIterative(0);



  //广度优先遍历 (BFS)
  function bfs(nodeId, adjList = graph) {
    const queue = [nodeId];
    const visited = new Set();
  
    while (queue.length > 0) {
      const currentNode = queue.shift(); // 弹出队头元素（先进先出）
      if (!visited.has(currentNode)) {
        visited.add(currentNode);
        console.log(currentNode);
  
        adjList[currentNode].forEach((neighbor) => {
          if (!visited.has(neighbor)) {
            queue.push(neighbor); // 把未访问过的相邻节点加入队列
          }
        });
      }
    }
  }
  
  // 从节点0开始广度优先遍历
  bfs(0);